/*
 * @Author: 'zhangkeqq' '2211709169@qq.com'
 * @Date: 2025-07-09 17:20:23
 * @LastEditors: 'zhangkeqq' '2211709169@qq.com'
 * @LastEditTime: 2025-07-10 11:59:01
 * @FilePath: \original_wx\miniprogram\utils\request.js
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import{env} from './env.js'
class WxRequest {
  //定义实例属性，用来设置默认请求参数
  defaults = {
    baseURL: env.baseURL, //请求的基准地址
    url: '', //接口请求的路径
    data: null,
    method: 'GET',
    header: {
      'Content-type': 'application/json'
    },
    timeout: 60000, //默认的超时时间，小程序默认的超时时长是1分钟
    isLoading: true // 控制是否使用默认的 loading，默认值是 true 表示使用默认的 loading
  }
  // 定义拦截器对象
  // 需要包含请求拦截器以及响应拦截器，方便在请求之前以及响应以后时进行逻辑处理
  interceptors = {
    // 请求拦截器
    // 在请求发送之前，对请求参数进行新增或者修改
    request: (config) => config,

    // 响应拦截器
    // 在服务器响应数据以后，对服务器响应的数据进行逻辑处理
    response: (response) => response
  }

  // 定义数组队列
  // 初始值需要是一个空数组，用来存储请求队列、存储请求标识
  queue = []

  constructor(params = {}) {
    Object.assign({}, this.defaults, params)
  }
  request(options) {
    //地址拼接
    options.url = this.defaults.baseURL + options.url
    // 在请求发送之前，调用请求拦截器，新增和修改请求参数
    options = this.interceptors.request(options)

    if (options.isLoading && options.method !== 'UPLOAD') {
      // 判断 queue 队列是否为空，如果是空，就显示 loading
      // 如果不是空，就不显示 loading，不调用 wx.showLoading()
      this.queue.length === 0 && wx.showLoading()
      // 然后立即向 queue 数组队列中添加请求标识
      // 每个标识代表是一个请求，标识是自定义的
      this.queue.push('request')
    }
    return new Promise((resolve, reject) => {
      if (options.method === 'UPLOAD') {
        wx.uploadFile({
          ...options,
          success: (res) => {
            // 需要将服务器返回的 JSON 字符串 通过 JSON.parse 转成对象
            res.data = JSON.parse(res.data)

            // 合并参数
            const mergeRes = Object.assign({}, res, {
              config: options,
              isSuccess: true
            })

            resolve(this.interceptors.response(mergeRes))
          },
          fail: (err) => {
            // 合并参数
            const mergeErr = Object.assign({}, err, {
              config: options,
              isSuccess: false
            })

            reject(this.interceptors.response(mergeErr))
          }
        })
      } else {
        wx.request({
          ...options,
          success: (res) => {
            // 合并参数
            const mergeRes = Object.assign({}, res, {
              config: options,
              isSuccess: true
            })
            resolve(this.interceptors.response(mergeRes))
          },
          fail: (err) => {
            //合并参数
            const mergeErr = Object.assign({}, err, {
              config: options,
              isSuccess: false
            })
            reject(this.interceptors.response(mergeErr))
          },
          // 接口调用结束的回调函数（调用成功、失败都会执行）
          complete: () => {
            if (options.isLoading) {
              // 在每一个请求结束以后，都会执行 complete 回调函数
              // 每次从 queue 队列中删除一个标识
              this.queue.pop()

              this.queue.length === 0 && this.queue.push('request')
              this.timerId = setTimeout(() => {
                this.queue.pop()

                // 在删除标识以后，需要判断目前 queue 数组是否为空
                // 如果是空，说明并发请求完成了
                // 就需要隐藏 loading，要调用 wx.hideLoading()
                this.queue.length === 0 && wx.hideLoading()

                clearTimeout(this.timerId)
              }, 1)
            }
          }
        })
      }


    })
  }

  // 封装get方法
  get(url, data = {}, config = {}) {
    return this.request(Object.assign({
      url,
      data,
      method: 'Get'
    }, config))
  }
  // 封装 DELETE 实例方法
  delete(url, data = {}, config = {}) {
    return this.request(Object.assign({
      url,
      data,
      method: 'DELETE'
    }, config))
  }

  // 封装 POST 实例方法
  post(url, data = {}, config = {}) {
    return this.request(Object.assign({
      url,
      data,
      method: 'POST'
    }, config))
  }

  // 封装 PUT 实例方法
  put(url, data = {}, config = {}) {
    return this.request(Object.assign({
      url,
      data,
      method: 'PUT'
    }, config))
  }

  // 用来处理并发请求
  all(...promise) {
    // 通过展开运算符接收传递的参数
    // 那么展开运算符会将传入的参数转成数组
    return Promise.all(promise)
  }

  /**
   * @description upload 实例方法，用来对 wx.uploadFile 进行封装
   * @param {*} url 文件的上传地址、接口地址
   * @param {*} filePath 要上传的文件资源路径
   * @param {*} name 文件对应的 key
   * @param {*} config 其他配置项
   */

  upload(url, filePath, name = 'file', config = {}) {
    return this.request(
      Object.assign({
        url,
        filePath,
        name,
        method: 'UPLOAD'
      }, config)
    )
  }

}

export default WxRequest